package com.iphanta.community.activity.voting.service.impl;

import com.iphanta.community.activity.voting.entity.Ranking;
import com.iphanta.community.activity.voting.entity.TimeRange;
import com.iphanta.community.activity.voting.entity.Vote;
import com.iphanta.community.activity.voting.influxdb.InfluxdbUtils;
import com.iphanta.community.activity.voting.influxdb.VoteNumFlux;
import com.iphanta.community.activity.voting.service.VoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author 墨声 E-mail: zehong.hongframe.huang@gmail.com
 * create time: 4/7/22 7:28 PM
 */
@Service
public class VoteServiceImpl implements VoteService {

    @Autowired
    private RedisTemplate<String, String> voteId;

    @Override
    public void vote(Vote vote) {
        vote.setTime(Instant.now());
        InfluxdbUtils.insert(vote);
    }

    @Override
    public List<Ranking> topN(String activityId, Integer n, Integer... voteType) {
        String flux = VoteNumFlux.rangeTopN(activityId, null, n, Arrays.asList(voteType));
        List<Vote> votes = InfluxdbUtils.query(flux, Vote.class);
        return convertRanking(votes);
    }

    @Override
    public List<Ranking> totalRanking(String activityId, Integer... voteType) {
        return null;
    }

    @Override
    public List<Ranking> rangeRanking(String activityId, TimeRange range, Integer... voteType) {
        String flux = VoteNumFlux.rangeRanking(activityId, range, Arrays.asList(voteType));
        List<Vote> votes = InfluxdbUtils.query(flux, Vote.class);
        Collections.sort(votes, ((o1, o2) -> (int) (o2.getVoteSum() - o1.getVoteSum())));
        return convertRanking(votes);
    }

    @Override
    public List<Ranking> recentlyRankingTopN(String activityId, Integer recentlyMinutes, Integer n, Integer... voteType) {
        String flux = VoteNumFlux.recentlyTopN(activityId, recentlyMinutes, n, Arrays.asList(voteType));
        List<Vote> votes = InfluxdbUtils.query(flux, Vote.class);
        return convertRanking(votes);
    }

    private List<Ranking> convertRanking(List<Vote> votes) {
        int index = 1;
        List<Ranking> rankings = new ArrayList<>();
        for (Vote vote : votes) {
            Ranking ranking = new Ranking();
            ranking.setRank(index);
            ranking.setDynamicId(Long.valueOf(vote.getDynamicId()));
            ranking.setVoteSum(vote.getVoteSum());
            ranking.setAccumulate(vote.getVoteCount());
            rankings.add(ranking);
            index++;
        }
        return rankings;
    }
}
